package com.ly.heart.service.king;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.spring.SpringUtils;
import com.ly.heart.domain.*;
import com.ly.heart.domain.king.BaseChildBo;
import com.ly.heart.domain.king.inventory.FSerialSubEntityBo;
import com.ly.heart.domain.king.order.FBillTypeIDBo;
import com.ly.heart.domain.king.order.OrderAuditBo;
import com.ly.heart.domain.king.order.OrderSubmitBo;
import com.ly.heart.domain.king.otherInbound.FACCEPTANCEBo;
import com.ly.heart.domain.king.otherInbound.FEntityBo;
import com.ly.heart.domain.king.otherInbound.OtherInboundBo;
import com.ly.heart.domain.request.KingBaseSingleRequest;
import com.ly.heart.domain.response.KingBaseResponse;
import com.ly.heart.domain.response.KingBaseResponseSuccessEntity;
import com.ly.heart.service.IKingOrgService;
import com.ly.heart.service.IKingOtherInboundService;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.heart.util.KingCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 其他入库单推送Service
 */
@Component
@Slf4j
public class KingOtherInboundPushService {

    private final SimpleDateFormat dateFormat = new SimpleDateFormat ( "yyyy-MM-dd" );

    @Resource
    private IKingOtherInboundService kingOtherInboundService;
    @Resource
    private IKingOrgService iKingOrgService;

    @Transactional( rollbackFor = Exception.class )
    public void push(String otherInboundId){
        KingOrgEntity orgEntity = iKingOrgService.getOne ( new LambdaQueryWrapper<KingOrgEntity>().eq ( KingOrgEntity :: getOrgId, CurrentUserUtil.getCompanyId () ).eq ( KingOrgEntity::getIsDisabled, false ) );
        if ( orgEntity == null ) {
            throw new CustomException ( "请先至系统管理中配置金蝶账套！" );
        }
        IdentifyInfo identifyInfo = KingCommonUtil.getIdentifyInfo ( orgEntity );
        KingOtherInboundEntity kingOtherInbound = kingOtherInboundService.selectKingOtherInboundEntityById(otherInboundId);
        if(Objects.isNull(kingOtherInbound)){
            throw new CustomException("其他入库单不存在！");
        }
        if(kingOtherInbound.getIsSend() == KingConstUtil.KING_DATA_IS_SEND_YES){
            throw new CustomException("该单据已推送金蝶,无需重复推送！");
        }
        try {
            K3CloudApi client = new K3CloudApi (identifyInfo);
            save(kingOtherInbound,client);
            submit(kingOtherInbound.getDocCode(),client);
            audit(kingOtherInbound.getDocCode(),client);
            updateSendSuccess(kingOtherInbound.getId());
            //调用即时库存更新
            kingOtherInboundService.updateRealTimeInventory(kingOtherInbound.getMaterialLists());
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException("推送其他入库单失败！");
        }
    }

    /**
     * 修改推送状态
     * @param otherInboundId
     * @return
     */
    private void updateSendSuccess(String otherInboundId){
        KingOtherInboundEntity kingOtherInbound = new KingOtherInboundEntity();
        kingOtherInbound.setId(otherInboundId);
        kingOtherInbound.setIsSend(KingConstUtil.KING_DATA_IS_SEND_YES);
        kingOtherInbound.setUpdateTime(DateUtils.getNowDate());
        kingOtherInbound.setUpdateBy(SecurityUtils.getLoginUser().getUser().getUserId());
        boolean flag = kingOtherInboundService.updateById(kingOtherInbound);
        if(!flag){
            throw new CustomException("修改推送状态失败！");
        }
    }

    /**
     * 金蝶其他入库单保存方法
     * @param otherInbound
     * @param client
     */
    public void save(KingOtherInboundEntity otherInbound, K3CloudApi client){
        try {
            String formId = KingConstUtil.STK_MISCELLANEOUS;
            KingBaseSingleRequest singleRequest = new KingBaseSingleRequest ();
            OtherInboundBo otherInboundBo = this.assembleOtherInbound(otherInbound);
            singleRequest.setModel(otherInboundBo);
            //调用接口
            String resultJson = client.save(formId, JSONObject.toJSONString(singleRequest));
            //用于记录结果
            Gson gson = new Gson();
            //对返回结果进行解析和校验
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("其他入库单推送成功: {}", gson.toJson(repoRet.getResult()));
                List<KingBaseResponseSuccessEntity> successEntities = baseResponse.getSuccessEntitys ();
                if(!CollectionUtils.isEmpty(successEntities)){
                    String docCode = successEntities.get(0).getNumber();
                    //修改为已推送状态
                    IKingOtherInboundService otherInboundService = SpringUtils.getBean(IKingOtherInboundService.class);
                    otherInboundService.update(new LambdaUpdateWrapper<KingOtherInboundEntity>().set(KingOtherInboundEntity::getIsSend,KingConstUtil.KING_DATA_IS_SEND_YES).eq(KingOtherInboundEntity::getDocCode,docCode));
                }
            } else {
                log.error("其他入库单推送失败: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 金蝶其他入库单提交方法
     * @param docCode
     * @param client
     */
    public void submit(String docCode, K3CloudApi client){
        try{
            OrderSubmitBo submitBo = new OrderSubmitBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            submitBo.setNumbers(numbers);
            String formId = KingConstUtil.STK_MISCELLANEOUS;
            String resultJson = client.submit(formId, JSON.toJSONString ( submitBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("其他入库单提交成功: {}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("其他入库单提交失败: {}",gson.toJson(repoRet.getResult().getResponseStatus()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 金蝶其他入库单审核方法
     * @param docCode
     * @param client
     */
    public void audit(String docCode,K3CloudApi client){
        try{
            OrderAuditBo auditBo = new OrderAuditBo();
            List<String> numbers = new ArrayList<>();
            numbers.add(docCode);
            auditBo.setNumbers(numbers);
            String formId = KingConstUtil.STK_MISCELLANEOUS;
            String resultJson = client.audit(formId,JSON.toJSONString ( auditBo ));
            Gson gson = new Gson();
            RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);
            KingBaseResponse baseResponse = JSONObject.parseObject ( gson.toJson ( repoRet.getResult ().getResponseStatus () ), KingBaseResponse.class );
            if (baseResponse.getIsSuccess()) {
                log.info("其他入库单审核成功:{}", gson.toJson(repoRet.getResult()));
            } else {
                log.error("其他入库单审核失败:{}",gson.toJson(repoRet.getResult().getResponseStatus()) );
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 组装其他入库单推送金蝶对象
     * @param otherInbound
     * @return
     */
    private OtherInboundBo assembleOtherInbound(KingOtherInboundEntity otherInbound){
        OtherInboundBo otherInboundBo = new OtherInboundBo();
        //单据编号
        otherInboundBo.setFBillNo(otherInbound.getDocCode());
        //单据类型
        FBillTypeIDBo FBillTypeID = new FBillTypeIDBo().setFNUMBER(otherInbound.getDocType());
        otherInboundBo.setFBillTypeID(FBillTypeID);
        //库存组织
        BaseChildBo FStockOrgId = new BaseChildBo().setFNumber(KingConstUtil.DEFAULT_ORG);
        otherInboundBo.setFStockOrgId(FStockOrgId);
        //库存方向
        otherInboundBo.setFStockDirect(otherInbound.getInventoryDirection());
        //日期
        otherInboundBo.setFDate(dateFormat.format(otherInbound.getInventoryTime()));
        //供应商
        BaseChildBo FSUPPLIERID = new BaseChildBo().setFNumber(otherInbound.getSupplierCode());
        otherInboundBo.setFSUPPLIERID(FSUPPLIERID);
        //部门
        BaseChildBo FDEPTID = new BaseChildBo().setFNumber(otherInbound.getDeptCode());
        otherInboundBo.setFDEPTID(FDEPTID);
        //验收员
        FACCEPTANCEBo FACCEPTANCE = new FACCEPTANCEBo().setFStaffNumber(otherInbound.getInspector());
        otherInboundBo.setFACCEPTANCE(FACCEPTANCE);
        //仓管员
        BaseChildBo FSTOCKERID = new BaseChildBo().setFNumber(otherInbound.getManagementBy());
        otherInboundBo.setFSTOCKERID(FSTOCKERID);
        //库存组
        BaseChildBo FSTOCKERGROUPID = new BaseChildBo().setFNumber(otherInbound.getInventoryGroup());
        otherInboundBo.setFSTOCKERGROUPID(FSTOCKERGROUPID);
        //货主类型
        otherInboundBo.setFOwnerTypeIdHead(otherInbound.getCargoOwnerType());
        //货主
        BaseChildBo FOwnerIdHead = new BaseChildBo().setFNumber(otherInbound.getCargoOwner());
        otherInboundBo.setFOwnerIdHead(FOwnerIdHead);
        //备注
        otherInboundBo.setFNOTE(otherInbound.getRemark());
        //todo 本位币
//        BaseChildBo FBaseCurrId = new BaseChildBo().setFNumber();
        //物料明细信息
        List<FEntityBo> FEntity = new ArrayList<>();
        if(!CollectionUtils.isEmpty(otherInbound.getMaterialLists())){
            List<KingOtherInboundMaterialEntity> materialLists = otherInbound.getMaterialLists();
            for(KingOtherInboundMaterialEntity otherInboundMaterial : materialLists){
                FEntityBo fEntityBo = new FEntityBo();
                KingOtherInboundMaterialDetailEntity otherInboundMaterialDetail = otherInboundMaterial.getMaterialDetail();
                Optional.ofNullable(otherInboundMaterialDetail).ifPresent(materialDetail -> {
                    //入库类型
                    fEntityBo.setFInStockType(materialDetail.getInboundType());
                    //库存状态
                    BaseChildBo FSTOCKSTATUSID = new BaseChildBo().setFNumber(materialDetail.getInventoryStatus());
                    fEntityBo.setFSTOCKSTATUSID(FSTOCKSTATUSID);
                    //BOM版本
                    BaseChildBo FBOMID = new BaseChildBo().setFNumber(materialDetail.getBomVer());
                    fEntityBo.setFBOMID(FBOMID);
                    //生产日期
                    fEntityBo.setFPRODUCEDATE(dateFormat.format(materialDetail.getManufactureTime()));
                    //计划跟踪号
                    fEntityBo.setFMTONO(materialDetail.getPlanTrackingCode());
                    //辅单位
                    BaseChildBo FExtAuxUnitId = new BaseChildBo().setFNumber(materialDetail.getAuxiliaryUnit());
                    fEntityBo.setFExtAuxUnitId(FExtAuxUnitId);
                    //实收数量(辅单位)
                    fEntityBo.setFExtAuxUnitQty(Integer.parseInt(materialDetail.getReceivedNumAuxiliaryUnit()));
                    //货主类型
                    fEntityBo.setFOWNERTYPEID(otherInbound.getCargoOwnerType());
                    //货主
                    BaseChildBo FOWNERID = new BaseChildBo().setFNumber(otherInbound.getCargoOwner());
                    fEntityBo.setFOWNERID(FOWNERID);
                    //保管者类型
                    fEntityBo.setFKEEPERTYPEID(materialDetail.getPreserverType());
                    //保管者
                    BaseChildBo FKEEPERID = new BaseChildBo().setFNumber(materialDetail.getPreserver());
                    fEntityBo.setFKEEPERID(FKEEPERID);
                    //入库日期
                    fEntityBo.setFInstockDate(dateFormat.format(otherInbound.getInventoryTime()));
                    //序列号
                    List<KingOtherInboundMaterialDetailSerialEntity> materialDetailSerials = materialDetail.getMaterialDetailSerials();
                    List<FSerialSubEntityBo> FSerialSubEntity = materialDetailSerials.stream().filter(Objects::nonNull).map(materialDetailSerial -> {
                        FSerialSubEntityBo fSerialSubEntityBo = new FSerialSubEntityBo();
                        //序列号
                        fSerialSubEntityBo.setFSerialNo(materialDetailSerial.getSerialCode());
                        //备注
                        fSerialSubEntityBo.setFSerialNote(materialDetailSerial.getRemark());
                        return fSerialSubEntityBo;
                    }).collect(Collectors.toList());
                    fEntityBo.setFSerialSubEntity(FSerialSubEntity);
                });
                //物料编码
                BaseChildBo FMATERIALID = new BaseChildBo().setFNumber(otherInboundMaterial.getMaterialCode());
                fEntityBo.setFMATERIALID(FMATERIALID);
                //单位
                BaseChildBo FUnitID = new BaseChildBo().setFNumber(otherInboundMaterial.getUnit());
                fEntityBo.setFUnitID(FUnitID);
                //收货仓库
                BaseChildBo FSTOCKID = new BaseChildBo().setFNumber(otherInboundMaterial.getReceiveWarehouseCode());
                fEntityBo.setFSTOCKID(FSTOCKID);
                //批号
                BaseChildBo FLOT = new BaseChildBo().setFNumber(otherInboundMaterial.getBatchNum());
                fEntityBo.setFLOT(FLOT);
                //实收数量
                fEntityBo.setFQty(Integer.parseInt(otherInboundMaterial.getReceiptsNum()));
                //备注
                fEntityBo.setFEntryNote(otherInboundMaterial.getRemark());
                FEntity.add(fEntityBo);
            }
        }
        otherInboundBo.setFEntity(FEntity);
        return otherInboundBo;
    }





}
